use std::collections::HashSet;

use crate::Validator;

pub struct LengthValidator<const MIN: usize, const MAX: usize>;

pub trait HasLength {
    fn len(&self) -> usize;

    fn is_empty(&self) -> bool {
        self.len() == 0
    }
}

impl HasLength for String {
    fn len(&self) -> usize {
        self.len()
    }
}

impl<T> HasLength for Vec<T> {
    fn len(&self) -> usize {
        self.len()
    }
}

impl<T> HasLength for HashSet<T> {
    fn len(&self) -> usize {
        self.len()
    }
}

impl<T: HasLength, const MIN: usize, const MAX: usize> Validator<T> for LengthValidator<MIN, MAX> {
    type Error = String;
    fn validate(&self, ident: Option<&str>, name: Option<&str>, data: &T) -> Result<(), String> {
        let data = data.len();
        if data < MIN || data > MAX {
            return Err(length_error(ident, name, data, MIN, MAX));
        }
        Ok(())
    }
}

fn length_error(
    ident: Option<&str>,
    name: Option<&str>,
    data: usize,
    min: usize,
    max: usize,
) -> String {
    let field = name.or(ident).unwrap_or_default();
    format!(
        "{}期望值长度范围是: {}~{}, 输入的长度是: {}",
        field, min, max, data
    )
}

#[cfg(test)]
mod tests {
    use crate::Validator;

    use super::LengthValidator;

    #[test]
    fn test_length_validator() {
        let name = Some(String::from("zhangsan"));
        let result = LengthValidator::<10, 10>.validate(None, None, &name);
        println!("{result:?}");
    }
}
